/**
 * 
 */
package tau.dimes.visualization.applet;

import processing.xml.XMLElement;
import tau.dimes.visualization.applet.data.Edge;
import tau.dimes.visualization.applet.data.Hop;
import tau.dimes.visualization.applet.data.Trace;
import tau.dimes.visualization.applet.data.TraceDataSet;

/**
 * Implements XML parsing functionality.
 */
class XmlParser
{
	private final String xmlSource;

	/**
	 * Constructs a new XmlParser.
	 * @param xmlSource XML source to parse.
	 */
	XmlParser(String xmlSource)
	{
		this.xmlSource = xmlSource;
	}

	/**
	 * Parses the XML source into a TraceDataSet.
	 * @return TraceDataSet constructed from parsed XML.
	 */
	public TraceDataSet parse()
	{
		TraceDataSet dataSet = new TraceDataSet();

		XMLElement traceDataElement = new XMLElement(xmlSource);
		XMLElement hopsElement = traceDataElement.getChild(0);
		XMLElement tracesElement = traceDataElement.getChild(1);

		parseHops(dataSet, hopsElement);
		parseTraces(dataSet, tracesElement);

		return dataSet;
	}

	private void parseHops(TraceDataSet dataSet, XMLElement hopsElement)
	{
		XMLElement hopElement;
		for (int i = 0; i < hopsElement.getChildCount(); i++)
		{
			hopElement = hopsElement.getChild(i);
			Hop hop = new Hop(hopElement.getStringAttribute("ID"), hopElement
				.getFloatAttribute("long"), hopElement.getFloatAttribute("lat"));
			dataSet.addHop(hop);
		}
	}

	private void parseTraces(TraceDataSet dataSet, XMLElement tracesElement)
	{
		XMLElement traceElement;
		XMLElement edgeElement;
		Hop source, destination, last;
		String sourceId, destinationId;
		Edge edge;
		Trace trace;

		for (int i = 0; i < tracesElement.getChildCount(); i++)
		{
			traceElement = tracesElement.getChild(i);
			trace = new Trace();
			last = null;

			for (int j = 0; j < traceElement.getChildCount(); j++)
			{
				edgeElement = traceElement.getChild(j);

				if (last == null)
				{
					sourceId = edgeElement.getStringAttribute("source");
					source = dataSet.getHops().get(sourceId);
				}
				else
					source = last;

				destinationId = edgeElement.getStringAttribute("dest");
				destination = dataSet.getHops().get(destinationId);
				edge = new Edge(source, destination);
				trace.add(edge);
				last = destination;
			}

			dataSet.addTrace(trace);
		}
	}
}